from common_data import *
from permission import *
from twisted.web import xmlrpc
from twisted.python import log
from sqlobject import dberrors
from datetime import datetime

class XMLRPC_UserResource( xmlrpc.XMLRPC ):
    _permissions = {
        'listUsers':            PERMISSION_REQUIREMENT_GLOBAL_USER,
        'getUserByName':        PERMISSION_REQUIREMENT_GLOBAL_USER,
        'getUserByID':          PERMISSION_REQUIREMENT_GLOBAL_USER,
        'addUser':              PERMISSION_REQUIREMENT_GLOBAL_ADMIN,
        'delUser':              PERMISSION_REQUIREMENT_GLOBAL_ADMIN,
        'updateUserPassword':   PERMISSION_REQUIREMENT_GLOBAL_USER,
        'updateUserIPAddress':  PERMISSION_REQUIREMENT_GLOBAL_USER,
    }
        
    def __init__(self):
        """ load config
        """
        log.msg( 'User resource init' )
        xmlrpc.XMLRPC.__init__(self)
        
    def xmlrpc_listUsers(self):
        """return list of configured users"""
                    
        try:
            users = User.select( orderBy=User.q.id )
        except:
            log.err( 'could not retrieve users' )
            log.err()
            raise xmlrpc.Fault( 123, 'could not retrieve users' )
        
        return list( ( user.id, user.name ) for user in users )
    
    xmlrpc_listUsers.signature = [['array']]
    
    def xmlrpc_getUserByName(self, user_name ):
        """get user by user name"""
        
        if not str( user_name ):
            raise xmlrpc.Fault( 123, 'invalid argument' )
        
        try:
            user = User.selectBy( name = str( user_name ) ).getOne()
        except SQLObjectNotFound:
            raise xmlrpc.Fault( 123, 'user not found' )
        except:
            log.err( 'could not retrieve user. user_name: %s' % str( user_name ) )
            log.err()
            raise xmlrpc.Fault( 123, 'could not retrieve user' )
                    
        return self.userResultToDict( user )
    
    xmlrpc_getUserByName.signature = [['array','string']]
    
    def xmlrpc_getUserByID(self, user_id ):
        """get user by user id"""
        
        if not int( user_id ):
            raise xmlrpc.Fault( 123, 'invalid argument' )
        
        user = getUserById( user_id )
                    
        return self.userResultToDict( user )
    
    xmlrpc_getUserByID.signature = [['array','int']]
        
    def xmlrpc_addUser(self, user_name, password ):
        """add new user"""
        
        if not str( user_name ) and not str( password ):
            raise xmlrpc.Fault( 123, 'missing user name or password' )
        
        try:
            u = User( name = str( user_name ), password = str( password ) )
        except dberrors.DuplicateEntryError:
            log.err( 'attempt to create duplicate user %s' % str( user_name ) )
            raise xmlrpc.Fault( 123, 'user name already exists' )
        except:
            log.err()
            raise xmlrpc.Fault( 123, 'unable to create new user' )

        return u.id
    
    xmlrpc_addUser.signature = [['int','string','string']]
        
    def xmlrpc_delUser(self, user_id ):
        """del user by user id"""
        
        if not str( user_id ):
            raise xmlrpc.Fault( 123, 'invalid argument' )
        
        user = getUserById( user_id )
        
        try:
            user.destroySelf()
        except:
            log.err( 'could not delete user. user_name: %d' % str( user_name ) )
            log.err()
            raise xmlrpc.Fault( 123, 'failed to delete user' )
            
        return user
    
    xmlrpc_delUser.signature = [['array','int']]
    
    def xmlprc_updateUserPassword(self, user_id, new_password ):
        """update the password of an existing user"""
        
        if not int( user_id ) or not str( new_password ):
            raise xmlrpc.Fault( 123, 'missing required information' )
        
        user = getUserById( user_id )
        
        try:
            user.password = new_password
        except:
            log.err()
            raise xmlrpc.Fault( 123, 'unable to set new password' )
            
        return True
    
    xmlprc_updateUserPassword.signature = [['bool','int','string']]
    
    def xmlrpc_updateUserIPAddress(self, user_id, new_ip ):
        """add or replace the ip currently registered for this user"""
        
        if not int( user_id ) or not str( new_ip ):
            raise xmlrpc.Fault( 123, 'invalid arguments' )
        
        user = getUserById( user_id )
        
        user.ip_address = str( new_ip )
        user.ip_address_modified_time = datetime.now()
        
        return True
    
    xmlrpc_updateUserIPAddress.signature = [['bool','int','string']]
    
    def userResultToDict(self, user ):
        result = dict()
        result['id'] = user.id
        result['name'] = user.name
        result['password'] = user.password
        result['creation_time'] = xmlrpc.DateTime( user.creation_time ).value
        result['modified_time'] = xmlrpc.DateTime( user.modified_time ).value
        result['party'] = user.party.id
        
        return result